/******************************************************************************
 * 
 *Taylor Chan's works,just for practice!
 * 
 *****************************************************************************/
package com.cq.thinkinjava.concurret.corparation;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


class Blocker {
    synchronized void waitingCall() {
      try {
        while(!Thread.interrupted()) {
          wait();
          System.out.print(Thread.currentThread() + " ");
        }
      } catch(InterruptedException e) {
        // OK to exit this way
      }
    }
    synchronized void prod() { notify(); }
    synchronized void prodAll() { notifyAll(); }
  }

  class Task implements Runnable {//唤醒只是针对锁定的对象
    static Blocker blocker = new Blocker();
    public void run() { blocker.waitingCall(); }
  }

  class Task2 implements Runnable {
    // A separate Blocker object:
    static Blocker blocker = new Blocker();
    public void run() { blocker.waitingCall(); }
  }

  public class NotifyVsNotifyAll {
    public static void main(String[] args) throws Exception {
      ExecutorService exec = Executors.newCachedThreadPool();
      for(int i = 0; i < 5; i++)
        exec.execute(new Task());
      
      exec.execute(new Task2());
      
      Timer timer = new Timer();
      timer.scheduleAtFixedRate(new TimerTask() {
        boolean prod = true;
        public void run() {
          if(prod) {
            System.out.print("\nnotify() ");
            Task.blocker.prod();
            prod = false;
          } else {
            System.out.print("\nnotifyAll() ");
            Task.blocker.prodAll();
            prod = true;
          }
        }
      }, 400, 400); // Run every .4 second
      TimeUnit.SECONDS.sleep(5); // Run for a while...
      timer.cancel();
      System.out.println("\nTimer canceled");
      TimeUnit.MILLISECONDS.sleep(500);
      System.out.print("Task2.blocker.prodAll() ");
      Task2.blocker.prodAll();
      TimeUnit.MILLISECONDS.sleep(500);
      System.out.println("\nShutting down");
      exec.shutdownNow(); // Interrupt all tasks
    }
  } /* Output: (Sample)
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main]
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main]
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main]
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main]
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-5,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-2,5,main]
  notify() Thread[pool-1-thread-1,5,main]
  notifyAll() Thread[pool-1-thread-1,5,main] Thread[pool-1-thread-2,5,main] Thread[pool-1-thread-3,5,main] Thread[pool-1-thread-4,5,main] Thread[pool-1-thread-5,5,main]
  Timer canceled
  Task2.blocker.prodAll() Thread[pool-1-thread-6,5,main]
  Shutting down
  *///:~

